const path = require('path');
const Server = require('@colpu/core');
const EVENT_CONF = require('./config/development.event');
const app = new Server();
const crypto = require('crypto');
const NODE_ENV = app.env;
const port = app.port;

// 将中间件处理前置，不能用use放在router后面
app.middleware.unshift(webpackCompiler);
app.start(() => {
  // 开发模式下向主进程发消息
  if (NODE_ENV === 'development') {
    process.send({
      action: 'reload',
      port
    });
  }
});

// 资源分发
async function webpackCompiler(ctx, next) {
  let fileContent;
  try {
    fileContent = await readMemoryFile(ctx.path);
  } catch (err) {
    console.error(err);
    return await next();
  }

  // 不存在文件则跳出中间件
  if (!fileContent) {
    return await next();
  }

  // 设置头部信息
  // ctx.set('Cache-Control', 'no-cache, no-transform');
  // ctx.set('X-Accel-Buffering', 'no');
  // ctx.set('Accept-Ranges', 'bytes');
  // ctx.set('Connection', 'keep-alive');
  ctx.status = 200;
  // ctx.set('Accept-Ranges', 'bytes');

  if (ctx.req.headers.range) {
    const ranges = parseRange(fileContent.length, ctx.req.headers.range);
    if (ranges === -1) {
      ctx.res.setHeader('Content-Range', 'bytes */' + fileContent.length);
      ctx.res.statusCode = 416;
    }

    if (ranges !== -2 && ranges.length === 1) {
      ctx.res.statusCode = 206;
      const length = fileContent.length;
      ctx.res.setHeader(
        'Content-Range',
        'bytes ' + ranges[0].start + '-' + ranges[0].end + '/' + length
      );
      fileContent = fileContent.slice(ranges[0].start, ranges[0].end + 1);
    }
  }

  ctx.type = path.extname(ctx.path);

  ctx.flushHeaders();
  ctx.body = fileContent;
}

let handlers = {};
process.on(EVENT_CONF.EVENT_MESSAGE, msg => {
  if (handlers[msg.key] && msg.action === EVENT_CONF.EVENT_FILE_READ_OK) {
    handlers[msg.key].resolve(msg.content);
  } else {
    handlers[msg.key].resolve(null);
  }
  delete handlers[msg.key];
});

/**
 * @function readMemoryFile 读取文件方法
 * @param {String} fileName 要读取的文件
 */
function readMemoryFile(fileName) {
  const uuid = crypto.createHash('md5').update(fileName + Date.now()).digest('hex');
  return new Promise((resolve, reject) => {
    let handler = {
      key: uuid,
      resolve,
      reject
    };
    handlers[uuid] = handler;

    process.send({
      action: EVENT_CONF.EVENT_FILE_READ,
      fileName,
      key: uuid
    });
  });
};
